package com.qire.manhua.model.viewModel.impl;

import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.CountDownTimer;
import android.view.View;
import android.view.inputmethod.InputMethodManager;

import com.qire.antscore.annotation.PropertyObserve;
import com.qire.common.support.base.BaseViewModel;
import com.qire.common.basic.StringUtil;
import com.qire.common.utils.ToastHelper;
import com.qire.manhua.R;
import com.qire.manhua.controller.LoginGuideController;
import com.qire.manhua.databinding.ActivityLoginGuideBinding;
import com.qire.common.support.CustomLoadDialog;
import com.qire.manhua.dal.service.LoginGuideService;
import com.qire.manhua.model.enumeration.AccountBusinessPanelLayout;
import com.qire.manhua.model.viewModel.ILoginGuideViewModel;

import net.yslibrary.android.keyboardvisibilityevent.util.UIUtil;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class LoginGuideViewModel extends BaseViewModel<ILoginGuideViewModel> {

    private final LoginGuideService loginGuideService = new LoginGuideService(this);

    private Drawable loginBgYellowRound;
    private Drawable loginBgGreyRound;
    private final String GetCodeCountDownFormat = "重新获取(%ss)";
    private final ArrayList<AccountBusinessPanelLayout> pageStack = new ArrayList<>();
    private AccountBusinessPanelLayout currentPanelLayout = null;

    // region # 属性
    private String phoneNumber;
    private String registerPassword;
    private String newPassword;
    private String changePassword;
    private String loginPassword;
    private String nickname;

    private boolean fetchVerifyCodeTextEnabled = true;
    private CharSequence fetchVerifyCodeText = "重新发送(60s)";
    private int verifyCode1 = -1;
    private int verifyCode2 = -1;
    private int verifyCode3 = -1;
    private int verifyCode4 = -1;
    // endregion

    //保存接口返回的验证码，用来做修改密码等需要验证的接口操作
    private String validateCode = "";

    private Activity activity;
    private ActivityLoginGuideBinding viewDataBinder;

    public LoginGuideViewModel() {
        set("agreeProtocol", false);
    }

    // region #属性操作
    public void setValidateCode(String validateCode) {
        this.validateCode = validateCode;
    }
    public String validateCode() {
        return this.validateCode;
    }

    public String phoneNumber() {
        return phoneNumber;
    }
    public String registerPassword() {
        return registerPassword;
    }
    public String newPassword() {
        return newPassword;
    }
    public String changePassword() {
        return changePassword;
    }
    public String loginPassword() {
        return loginPassword;
    }
    public String nickname() {
        return nickname;
    }

    public Boolean isAgreeProtocol() {
        return getToValue("agreeProtocol");
    }
    // endregion #属性操作

    // region # 属性校验
    public boolean phoneIsValid() {
        return StringUtil.notEmpty(phoneNumber) && StringUtil.isMobile(phoneNumber);
    }
    public boolean registerPasswordIsValid() {
        return StringUtil.notEmpty(registerPassword) && registerPassword.length() >= 8;
    }
    public boolean newPasswordIsValid() {
        return StringUtil.notEmpty(newPassword) && newPassword.length() >= 8;
    }
    public boolean nicknameIsValid() {
        return StringUtil.notEmpty(nickname);
    }
    public boolean nicknameIsIllegal() {
        Pattern pattern = Pattern.compile("[~#@*+%{}<>\\[\\]|\"\\_^]");///^[\x{4e00}-\x{9fa5}A-Za-z0-9]+$/u
        Matcher matcher = pattern.matcher(nickname);
        return matcher.find();
    }
    public boolean loginPasswordIsValid() {
        return StringUtil.notEmpty(loginPassword) && loginPassword.length() >= 8;
    }
    public boolean changePasswordIsValid() {
        return StringUtil.notEmpty(changePassword) && changePassword.length() >= 8;
    }
    public boolean verifyCodeIsValid() {
        return verifyCode1 >= 0 && verifyCode2 >= 0 && verifyCode3 >= 0 && verifyCode4 >= 0;
    }
    // endregion

    //region    #附加管理 begin

    /**
     * 附加属性绑定
     * @param activity
     * @param viewDataBinder 页面数据绑定器
     */
    public void onAddition(Activity activity, ActivityLoginGuideBinding viewDataBinder) {
        this.activity = activity;
        this.viewDataBinder = viewDataBinder;

        loginBgYellowRound = activity.getResources().getDrawable(R.drawable.app_login_guide_background_yellow, null);
        loginBgGreyRound   = activity.getResources().getDrawable(R.drawable.app_login_guide_background_gray, null);

        LoginGuideController controller = viewDataBinder.getLoginGuideController();
        viewDataBinder.editRegisterPassword.addEventDrawable(R.drawable.app_compound_icon_pwd_ciphertext, "plaintextBtn");
        viewDataBinder.editRegisterPassword.setCompoundEventListener("plaintextBtn", controller::compoundEventPlaintextBtnOnClick);

        viewDataBinder.editLoginPassword.addEventDrawable(R.drawable.app_compound_icon_pwd_ciphertext, "plaintextBtn");
        viewDataBinder.editLoginPassword.setCompoundEventListener("plaintextBtn", controller::compoundEventPlaintextBtnOnClick);

        viewDataBinder.editResetPassword.addEventDrawable(R.drawable.app_compound_icon_pwd_ciphertext, "plaintextBtn");
        viewDataBinder.editResetPassword.setCompoundEventListener("plaintextBtn", controller::compoundEventPlaintextBtnOnClick);

        viewDataBinder.editNewPassword.addEventDrawable(R.drawable.app_compound_icon_pwd_ciphertext, "plaintextBtn");
        viewDataBinder.editNewPassword.setCompoundEventListener("plaintextBtn", controller::compoundEventPlaintextBtnOnClick);

        initPanelLayout();

        viewDataBinder.loginGuidePhoneNumber.requestFocus();
        viewDataBinder.loginGuidePhoneNumber.postDelayed(()-> UIUtil.showKeyboard(activity, viewDataBinder.loginGuidePhoneNumber), 300);
    }

    @Override
    protected void onCleared() {
        super.onCleared();
        viewDataBinder = null;
        activity = null;
        timer.cancel();
    }

    //endregion #附加管理 end

    // region #Model业务相关

    /**
     * 验证电话号码
     */
    public void phoneAuth() {
        if(!phoneIsValid()) {
            ToastHelper.showToast("手机号码输入错误");
            resetGetCodeButton();
            return;
        }
        loginGuideService.phoneAuth();
    }

    /**
     * 更新手机验证结果
     * @param haveRegister 是否有注册
     * @param havePassword 是否设置过密码
     * @param haveNickName 是否设置过昵称
     */
    public void updateMobileAuthInfo(boolean haveRegister, boolean havePassword, boolean haveNickName) {
        //手机身份信息验证API调用后回调处理：验证手机是否已注册等信息,确定其打开的登录框页面顺序

        AccountBusinessPanelLayout lastPanelLayout = null;

        if(haveRegister) {
            lastPanelLayout = AccountBusinessPanelLayout.PhoneRegister;
            AccountBusinessPanelLayout.CodeVerify.addNext(lastPanelLayout);
            gotoPage(AccountBusinessPanelLayout.CodeVerify);
            fetchVerificationCode();
        } else {
            if(havePassword) {
                AccountBusinessPanelLayout.SetPassword.addNext(AccountBusinessPanelLayout.PhoneLogin);
                AccountBusinessPanelLayout.CodeVerify.addNext(AccountBusinessPanelLayout.SetPassword);
                gotoPage(AccountBusinessPanelLayout.CodeVerify);
                fetchVerificationCode();
            } else {
                lastPanelLayout = AccountBusinessPanelLayout.PhoneLogin;
                gotoPage(AccountBusinessPanelLayout.PhoneLogin);
            }
        }

        if(haveNickName) {
            lastPanelLayout.addNext(AccountBusinessPanelLayout.NicknameSet);
        }

    }

    /**
     * 获取验证码
     */
    public void fetchVerificationCode() {
        startCountDown();
        requestVerifyCode1Focus();
        loginGuideService.fetchVerificationCode();
    }

    /**
     * 校验验证码
     */
    public void checkVerificationCode() {
        if(!verifyCodeIsValid()) {
            ToastHelper.showToast("无效的验证码");
            return;
        }
        loginGuideService.checkVerificationCode(verifyCode());
    }

    /**
     * 手机注册
     */
    public void phoneRegister() {
        if(!registerPasswordIsValid()) {
            ToastHelper.showToast("请输入登录密码");
            return ;
        }
        loginGuideService.phoneRegister(activity.getClass().getSimpleName());
    }

    /**
     * 手机登录
     */
    public void mobileLogin() {
        if(!loginPasswordIsValid()) {
            ToastHelper.showToast("请输入登录密码");
            return ;
        }
        loginGuideService.mobileLogin(activity.getClass().getSimpleName());
    }

    public void weChatLogin() {
        CustomLoadDialog.show(activity, "正在登录", true, null);
        loginGuideService.weChatLogin(activity.getClass().getSimpleName());
    }

    public void qqLogin() {
        CustomLoadDialog.show(activity, "正在登录", true, null);
        loginGuideService.qqLogin(activity.getClass().getSimpleName());
    }

    /**
     * 更新昵称
     */
    public void updateNickname() {
        if(!nicknameIsValid()) {
            ToastHelper.showToast("请输入昵称");
            return;
        }
        if(nicknameIsIllegal()) {
            ToastHelper.showToast("请输入合法的昵称，昵称中不能包含非法字符，只能由数字、字母、中文组成");
            return;
        }
        loginGuideService.updateNickname();
        switchPage();
    }

    /**
     * 找回密码
     */
    public void retrievePasswordAction() {
        if(!newPasswordIsValid()) {
            ToastHelper.showToast("请输入新密码");
            return ;
        }
        loginGuideService.retrievePasswordAction(validateCode());
    }

    /**
     * 修改密码
     */
    public void updatePasswordAction() {
        if(!changePasswordIsValid()) {
            ToastHelper.showToast("请输入登录密码");
            return ;
        }
        loginGuideService.updatePasswordAction(validateCode());
    }

    // endregion #Model业务相关

    // region #面板布局操作

    private void hideKeyBoard() {
        // 关闭软键盘
        View view = activity.getCurrentFocus();
        if(view == null)
            return;
        InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
    }

    private void restart() {
        pageStack.clear();
        setPhoneNumber("");
        setNickname("");
        setLoginPassword("");
        setRegisterPassword("");
        setNewPassword("");
        setChangePassword("");
    }
    private void initPanelLayout() {
        restart();
        gotoPage(AccountBusinessPanelLayout.LoginWay);
    }

    private void addPagePanel(AccountBusinessPanelLayout panelLayout) {
        pageStack.add(panelLayout);
    }

    private void refreshPanelLayoutVisible() {
        int[] layoutVisible = new int[7];
        Arrays.fill(layoutVisible, View.GONE);

        String pageTitle = "手机登录/注册";
        int skipBtnVisible = View.GONE;
        int forgotPasswordBtnVisible = View.INVISIBLE;

        if(currentPanelLayout != null) {
            pageTitle = currentPanelLayout.pageTitle;
            switch (currentPanelLayout) {
                case LoginWay :
                    layoutVisible[0] = View.VISIBLE;
                    break;
                case CodeVerify :
                    layoutVisible[1] = View.VISIBLE;
                    break;
                case PhoneRegister :
                    layoutVisible[2] = View.VISIBLE;
                    break;
                case NicknameSet :
                    layoutVisible[3] = View.VISIBLE;
                    skipBtnVisible = View.VISIBLE;
                    forgotPasswordBtnVisible = View.GONE;
                    break;
                case PhoneLogin :
                    layoutVisible[4] = View.VISIBLE;
                    forgotPasswordBtnVisible = View.VISIBLE;
                    pageTitle += StringUtil.replace("****", phoneNumber, 3) ;
                    break;
                case RetrievePassword :
                    layoutVisible[5] = View.VISIBLE;
                    break;
                case SetPassword :
                    layoutVisible[6] = View.VISIBLE;
                    break;
            }
        }

        put("title", pageTitle);
        put("skipBtnVisible", skipBtnVisible);
        put("forgotPasswordBtnVisible", forgotPasswordBtnVisible);
        put("panelBgRid", pageStack.isEmpty() ? R.drawable.app_login_guide_background_a : R.drawable.app_login_guide_background_b);
        put("layoutVisible", layoutVisible);
    }

    private void refreshPage(AccountBusinessPanelLayout page) {
        this.currentPanelLayout = page;
        hideKeyBoard();
        resetVerifyCode();
        resetGetCodeButton();

        refreshPanelLayoutVisible();

        AccountBusinessPanelLayout lastPage = pageStack.isEmpty() ? null : pageStack.get(pageStack.size() - 1);
        if(lastPage == page)
            pageStack.remove(lastPage);
    }

    public void gotoPage(AccountBusinessPanelLayout page) {
        if(currentPanelLayout != null)
            addPagePanel(currentPanelLayout);
        refreshPage(page);
    }

    public void backPage() {
        if(pageStack.isEmpty()) {
            activity.finish();
            return;
        }
        if(currentPanelLayout.isFinish) {
            activity.finish();
            return;
        }
        AccountBusinessPanelLayout lastPage = pageStack.get(pageStack.size() - 1);
        refreshPage(lastPage);
        pageStack.remove(lastPage);
    }

    public void switchPage() {
        if(currentPanelLayout == null)
            return;
        if(currentPanelLayout.next() == null){
            activity.finish();
            return;
        }
        if(currentPanelLayout.needRecycle())
            addPagePanel(currentPanelLayout);
        refreshPage(currentPanelLayout.next());
    }

    // endregion

    // region #手机号码验证阶段
    @PropertyObserve(name = "phoneNumber")
    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;

        put("phoneVerifyButtonEnabled", phoneIsValid());
        put("phoneVerifyButtonBackground", phoneIsValid() ? loginBgYellowRound : loginBgGreyRound);
        put("phoneVerifyButtonTextColor", phoneIsValid() ? "#1f1f1f" : "#d6d6d6");
        put("phoneVerifyButtonVisible", StringUtil.isEmpty(phoneNumber) ? View.GONE : View.VISIBLE);
        put("thirdPlatformLayoutVisible", StringUtil.isEmpty(phoneNumber) ? View.VISIBLE : View.GONE);

    }

    // endregion

    // region #验证码验证阶段
    /**
     * 获取验证码
     * @return 返回完整的4位验证码
     */
    public String verifyCode() {
        return String.format("%s%s%s%s", verifyCode1, verifyCode2, verifyCode3, verifyCode4);
    }

    /**
     * 重置验证码
     */
    private void resetVerifyCode() {
        proxy().setVerifyCode("", "", "", "");
        resetGetCodeButton();
    }

    /**
     * 将焦点归位到验证码起点位置。
     */
    public void requestVerifyCode1Focus() {
        viewDataBinder.verifyCode1.requestFocus();
        viewDataBinder.verifyCode1.postDelayed(() -> UIUtil.showKeyboard(activity, viewDataBinder.verifyCode1), 300);
    }

    /** 获取验证码倒计时*/
    public void startCountDown() {
        setFetchVerifyCodeText(String.format(GetCodeCountDownFormat, 60));
        setFetchVerifyCodeTextEnabled(false);
        timer.start();
    }

    /** 恢复获取验证码按钮*/
    public void resetGetCodeButton() {
        timer.cancel();
        setFetchVerifyCodeText("重新获取");
        setFetchVerifyCodeTextEnabled(true);
    }

    /** 验证码计时器*/
    private CountDownTimer timer = new CountDownTimer(60000, 1000) {
        @Override
        public void onTick(long l) {
            setFetchVerifyCodeText(String.format(GetCodeCountDownFormat, l/1000));
        }
        @Override
        public void onFinish() {
            resetGetCodeButton();
        }
    };

    /**
     * 设置并更新获取验证码按钮的文本，该文本在重新获取验证码后会进入倒计时60s
     * @param fetchVerifyCodeText 更新的文本
     */
    private void setFetchVerifyCodeText(CharSequence fetchVerifyCodeText) {
        this.fetchVerifyCodeText = fetchVerifyCodeText;
        put("fetchVerifyCodeText", this.fetchVerifyCodeText);
    }

    /**
     * 设置并更新获取验证码按钮的失效状态
     * @param enabled true为有效false为失效
     */
    private void setFetchVerifyCodeTextEnabled(boolean enabled) {
        fetchVerifyCodeTextEnabled = enabled;
        put("fetchVerifyCodeTextColor", fetchVerifyCodeTextEnabled ? "#ffcc1c" : "#ffcc1c");
        put("fetchVerifyCodeTextEnabled", fetchVerifyCodeTextEnabled);
    }

    /**
     * 刷新验证码确认按钮状态
     */
    private void refreshVerifyBtn() {
        put("verifyBtnEnabled", verifyCodeIsValid());
        put("verifyBtnBackground", verifyCodeIsValid() ? loginBgYellowRound : loginBgGreyRound);
        put("verifyBtnTextColor", verifyCodeIsValid() ? "#1f1f1f" : "#d6d6d6");
    }

    /**
     * 以下是4个验证码输入框的状态监听，如果输入框内容发生改变则会触发观察者消息
     */
    @PropertyObserve(name = "verifyCode1")
    public void setVerifyCode1(String verifyCode1) {
        try {
            int codeValue = Integer.valueOf(verifyCode1);
            // 解决光标位置问题导致可能最新输入的字符在旧字符前需要判断故做一下数值运算处理，始终使用最新值替换旧值；
            if(codeValue != this.verifyCode1) {
                this.verifyCode1 = codeValue % 10 == this.verifyCode1 ? codeValue / 10 : codeValue % 10;
            }
            viewDataBinder.verifyCode2.requestFocus();
        } catch(Exception e) {
            this.verifyCode1 = -1;
        }
        refreshVerifyBtn();
    }
    @PropertyObserve(name = "verifyCode2")
    public void setVerifyCode2(String verifyCode2) {
        try {
            int codeValue = Integer.valueOf(verifyCode2);
            if(codeValue != this.verifyCode2) {
                this.verifyCode2 = codeValue % 10 == this.verifyCode2 ? codeValue / 10 : codeValue % 10;
            }
            viewDataBinder.verifyCode3.requestFocus();
        } catch(Exception e) {
            this.verifyCode2 = -1;
            viewDataBinder.verifyCode1.requestFocus();
        }
        refreshVerifyBtn();
    }
    @PropertyObserve(name = "verifyCode3")
    public void setVerifyCode3(String verifyCode3) {
        try {
            int codeValue = Integer.valueOf(verifyCode3);
            if(codeValue != this.verifyCode3) {
                this.verifyCode3 = codeValue % 10 == this.verifyCode3 ? codeValue / 10 : codeValue % 10;
            }
            viewDataBinder.verifyCode4.requestFocus();
        } catch(Exception e) {
            this.verifyCode3 = -1;
            viewDataBinder.verifyCode2.requestFocus();
        }
        refreshVerifyBtn();
    }
    @PropertyObserve(name = "verifyCode4")
    public void setVerifyCode4(String verifyCode4) {
        try {
            int codeValue = Integer.valueOf(verifyCode4);
            if(codeValue != this.verifyCode4) {
                this.verifyCode4 = codeValue % 10 == this.verifyCode4 ? codeValue / 10 : codeValue % 10;
            }
        } catch(Exception e) {
            this.verifyCode4 = -1;
            viewDataBinder.verifyCode3.requestFocus();
        }
        refreshVerifyBtn();
    }
    // endregion

    // region #注册阶段
    @PropertyObserve(name = "registerPassword")
    public void setRegisterPassword(String registerPassword) {
        this.registerPassword = registerPassword;
        put("registerBtnEnabled", registerPasswordIsValid());
        put("registerBtnBackground", registerPasswordIsValid() ? loginBgYellowRound : loginBgGreyRound);
        put("registerBtnTextColor", registerPasswordIsValid() ? "#1f1f1f" : "#d6d6d6");
    }
    // endregion

    // region #设置密码阶段
    @PropertyObserve(name = "newPassword")
    public void setNewPassword(String newPassword) {
        this.newPassword = newPassword;

        put("retrievePasswordBtnEnabled", newPasswordIsValid());
        put("retrievePasswordBtnBackground", newPasswordIsValid() ? loginBgYellowRound : loginBgGreyRound);
        put("retrievePasswordBtnTextColor", newPasswordIsValid() ? "#1f1f1f" : "#d6d6d6");
    }
    // endregion

    // region #昵称设置阶段
    @PropertyObserve(name = "nickname")
    public void setNickname(String nickname) {
        this.nickname = nickname;

        put("nikeNameButtonEnabled", nicknameIsValid());
        put("nikeNameButtonBackground", nicknameIsValid() ? loginBgYellowRound : loginBgGreyRound);
        put("nikeNameButtonTextColor", nicknameIsValid() ? "#1f1f1f" : "#d6d6d6");
    }
    // endregion

    // region #手机登录阶段
    @PropertyObserve(name = "loginPassword")
    public void setLoginPassword(String loginPassword) {
        this.loginPassword = loginPassword;

        put("loginButtonEnabled", loginPasswordIsValid());
        put("loginButtonBackground", loginPasswordIsValid() ? loginBgYellowRound : loginBgGreyRound);
        put("loginButtonTextColor", loginPasswordIsValid() ? "#1f1f1f" : "#d6d6d6");
    }
    // endregion

    // region #修改密码阶段
    @PropertyObserve(name = "changePassword")
    public void setChangePassword(String changePassword) {
        this.changePassword = changePassword;

        put("changePasswordBtnEnabled", changePasswordIsValid());
        put("changePasswordBtnBackground", changePasswordIsValid() ? loginBgYellowRound : loginBgGreyRound);
        put("changePasswordBtnTextColor", changePasswordIsValid() ? "#1f1f1f" : "#d6d6d6");
    }
    // endregion

}
